# services/bank_service.py
# 在文件开头添加
# services/bank_service.py
from typing import List, Optional
from datetime import datetime, timedelta  # 添加 timedelta 导入
from sqlalchemy.orm import Session
from model import UserInfo, CardInfo, TradeInfo, Deposit  # 修正导入路径
# from schemas import UserCreate, CardCreate, TradeCreate  # schemas.py 不存在，暂时注释
import hashlib
import random
import string

# ... 其余代码保持不变 ...


def get_user_by_username(db: Session, username: str) -> Optional[UserInfo]:
    """根据用户名/银行卡号获取用户"""
    return db.query(UserInfo).filter(UserInfo.username == username).first()


def authenticate_user(db: Session, username: str, password: str) -> Optional[UserInfo]:
    """验证用户密码"""
    user = get_user_by_username(db, username)
    if not user:
        return None

    # 计算密码的MD5哈希
    hashed_password = hashlib.md5(password.encode()).hexdigest()
    if hashed_password != user.password:
        return None

    return user


def create_user(db: Session, user: UserCreate) -> UserInfo:
    """创建新用户"""
    # 加密密码
    hashed_password = hashlib.md5(user.password.encode()).hexdigest()

    db_user = UserInfo(
        username=user.username,
        password=hashed_password,
        real_name=user.real_name,
        id_card=user.id_card,
        phone=user.phone,
        address=user.address,
        role=user.role
    )

    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user


def generate_card_number() -> str:
    """生成随机银行卡号"""
    prefix = "10103576"
    suffix = ''.join(random.choices(string.digits, k=8))
    return prefix + suffix


def create_card(db: Session, card: CardCreate, user_id: int) -> CardInfo:
    """创建新银行卡"""
    # 生成卡号
    card_number = generate_card_number()

    db_card = CardInfo(
        card_number=card_number,
        user_id=user_id,
        card_type=card.card_type,
        balance=card.balance,
        status=card.status,
        currency=card.currency,
        open_date=datetime.now()
    )

    if card.card_type in [2, 3, 4, 6, 7, 8]:
        # 定期存款设置到期日
        if card.card_type == 2:  # 定期一年
            db_card.due_date = datetime.now() + timedelta(days=365)
        elif card.card_type == 3:  # 定期二年
            db_card.due_date = datetime.now() + timedelta(days=730)
        elif card.card_type == 4:  # 定期三年
            db_card.due_date = datetime.now() + timedelta(days=1095)
        elif card.card_type == 6:  # 零存整取一年
            db_card.due_date = datetime.now() + timedelta(days=365)
        elif card.card_type == 7:  # 零存整取二年
            db_card.due_date = datetime.now() + timedelta(days=730)
        elif card.card_type == 8:  # 零存整取三年
            db_card.due_date = datetime.now() + timedelta(days=1095)

    db.add(db_card)
    db.commit()
    db.refresh(db_card)
    return db_card


def get_card_by_number(db: Session, card_number: str) -> Optional[CardInfo]:
    """根据卡号获取银行卡信息"""
    return db.query(CardInfo).filter(CardInfo.card_number == card_number).first()


def deposit(db: Session, card_number: str, amount: float, remark: str) -> TradeInfo:
    """存款操作"""
    card = get_card_by_number(db, card_number)
    if not card:
        raise ValueError("银行卡不存在")

    if amount <= 0:
        raise ValueError("存款金额必须大于0")

    # 更新余额
    card.balance += amount

    # 创建交易记录
    trade = TradeInfo(
        card_number=card_number,
        trade_type="deposit",
        amount=amount,
        remark=remark
    )

    db.add(trade)
    db.commit()
    db.refresh(card)
    return trade


def withdraw(db: Session, card_number: str, amount: float, password: str, remark: str) -> TradeInfo:
    """取款操作"""
    card = get_card_by_number(db, card_number)
    if not card:
        raise ValueError("银行卡不存在")

    if amount <= 0:
        raise ValueError("取款金额必须大于0")

    if card.balance < amount:
        raise ValueError("余额不足")

    # 这里应该验证密码，实际应用中密码会存储在用户表中
    # 简化处理，假设密码正确
    # 实际应用中应该从用户表获取密码并验证

    # 更新余额
    card.balance -= amount

    # 创建交易记录
    trade = TradeInfo(
        card_number=card_number,
        trade_type="withdraw",
        amount=amount,
        remark=remark
    )

    db.add(trade)
    db.commit()
    db.refresh(card)
    return trade


def transfer(db: Session, from_card: str, to_card: str, amount: float, password: str, remark: str) -> TradeInfo:
    """转账操作"""
    from_card_obj = get_card_by_number(db, from_card)
    to_card_obj = get_card_by_number(db, to_card)

    if not from_card_obj:
        raise ValueError("转出账户不存在")

    if not to_card_obj:
        raise ValueError("转入账户不存在")

    if amount <= 0:
        raise ValueError("转账金额必须大于0")

    if from_card_obj.balance < amount:
        raise ValueError("余额不足")

    # 验证密码
    # 这里应该验证密码，实际应用中密码会存储在用户表中
    # 简化处理，假设密码正确

    # 执行转账
    from_card_obj.balance -= amount
    to_card_obj.balance += amount

    # 创建转出交易记录
    from_trade = TradeInfo(
        card_number=from_card,
        trade_type="transfer",
        amount=amount,
        other_card=to_card,
        remark=remark
    )

    # 创建转入交易记录
    to_trade = TradeInfo(
        card_number=to_card,
        trade_type="transfer",
        amount=amount,
        other_card=from_card,
        remark=f"转入自{from_card}"
    )

    db.add(from_trade)
    db.add(to_trade)
    db.commit()
    db.refresh(from_card_obj)
    db.refresh(to_card_obj)

    return from_trade


def get_user_cards(db: Session, user_id: int) -> List[CardInfo]:
    """获取用户的所有银行卡"""
    return db.query(CardInfo).filter(CardInfo.user_id == user_id).all()


def get_card_transactions(db: Session, card_number: str, start_date: datetime = None,
                          end_date: datetime = None, trade_type: str = None) -> List[TradeInfo]:
    """
    获取银行卡的交易记录

    :param db: 数据库会话
    :param card_number: 银行卡号
    :param start_date: 起始日期（可选）
    :param end_date: 结束日期（可选）
    :param trade_type: 交易类型（可选）
    :return: 交易记录列表
    """
    query = db.query(TradeInfo).filter(TradeInfo.card_number == card_number)
    if start_date:
        query = query.filter(TradeInfo.create_time >= start_date)
    if end_date:
        query = query.filter(TradeInfo.create_time <= end_date)
    if trade_type:
        query = query.filter(TradeInfo.trade_type == trade_type)
    return query.all()